//
// Created by lwj12 on 25-7-18.
//

#ifndef TEST_7_18__SMART_POINTER_H
#define TEST_7_18__SMART_POINTER_H

#include<iostream>

namespace lwj
{
    template <typename T>
    class my_unique_ptr
    {
    public:
        explicit my_unique_ptr(T* ptr = nullptr) : _ptr(ptr) {}

        ~my_unique_ptr() noexcept
        {
            delete _ptr;
        }

        my_unique_ptr(const my_unique_ptr& ) = delete;
        my_unique_ptr& operator=(const my_unique_ptr&) = delete;

        my_unique_ptr(my_unique_ptr&& other) noexcept: _ptr(move(other._ptr)) {other._ptr = nullptr;}
        my_unique_ptr& operator=(my_unique_ptr&& other) noexcept
        {
            if(this != &other)
            {
                delete _ptr;
                _ptr = move(other._ptr);
                other._ptr = nullptr;
            }
            return *this;
        }

        T& operator*() const
        {
            return *_ptr;
        }

        T* operator->() const
        {
            return _ptr;
        }

        T* get() const
        {
            return _ptr;
        }

        // 释放所有权（不释放内存）
        T* release()
        {
            T* temp = _ptr;
            _ptr = nullptr;
            return temp;
        }

        // 替换资源
        void reset(T* ptr)
        {
            delete _ptr;
            _ptr = ptr;
        }

    private:
        T* _ptr;
    };

    template <typename T>
    class my_shared_ptr
    {
    public:
        explicit my_shared_ptr(T* ptr = nullptr) : _ptr(ptr), _count(_ptr ? new int(1) : nullptr) {};
        ~my_shared_ptr() noexcept
        {
            if(_count && --(*_count) == 0)
            {
                delete _ptr;
                delete _count;
            }
            _ptr = nullptr;
            _count = nullptr;
        }

        my_shared_ptr(const my_shared_ptr& other) : _ptr(other._ptr), _count(other._count) {++(*_count);}
        my_shared_ptr& operator=(const my_shared_ptr& other)
        {
            if(this != &other)
            {
                
                _count = other._count;
                _ptr = other._ptr;
                if (_count) ++(*_count);
            }
            return *this;
        }

        my_shared_ptr(my_shared_ptr&& other)  noexcept : _ptr(other._ptr), _count(other._count)
        {
            other._count = nullptr;
            other._ptr = nullptr;
        }

        my_shared_ptr& operator=(my_shared_ptr&& other) noexcept
        {
            if(this != &other)
            {
                if(_count && --(*_count) == 0)
                {
                    delete _ptr;
                    delete _count;
                }
                _ptr = other._ptr;
                _count = other._count;
                other._count = nullptr;
                other._ptr = nullptr;
            }
            return *this;
        }

        T* get() const {return _ptr;}

        int use_count() const {return _count ? *_count : 0;}

        T& operator*() const {return *_ptr;}

        T* operator->() const {return _ptr;}

    private:
        T* _ptr;
        int* _count;
    };
}

#endif//TEST_7_18__SMART_POINTER_H
